home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
-
- main.c: Copyright (c) Kevin Hammond 1993. All rights reserved.
-
- This is the main module for the Gofer Mac interface.
-
- The routines in this module handle initialisation, the main event loop
- and top-level event dispatching.
-
- *****************************************************************************/
-
- #pragma segment GMain
-
- #include "mac.h"
- #include <AppleEvents.h>
- #include <Errors.h>
-
- CursHandle ibeamcurs, watchcurs; /* Ibeam and Watch cursors */
- CursHandle gccurs; /* Cursor used during GC */
- CCrsrHandle gccursc; /* Colour version of above */
-
- EventRecord myEvent; /* Main event record */
- Boolean WNEAvailable = FALSE; /* WaitNextEvent available */
- Boolean CCAvailable = FALSE; /* Colour Cursors available */
- Boolean CIAvailable = FALSE; /* Colour Icons available */
- Boolean HasAppleEvents = FALSE; /* Supports System-7 AppleEvents */
- Boolean inForeground = TRUE; /* Are we in the background? */
- Boolean MemoryInstalledOK = FALSE; /* True once the memory's been initialised */
- Boolean GoferInitialised = FALSE; /* True once the interface is initialised */
- Boolean InterpreterInitialised = FALSE; /* True once Gofer's completely initialised */
-
- short systemVersion = 0x0000; /* System software version */
- short goferWDRefNum = 0; /* Gofer's working directory's refnum */
- short gofervol = 0; /* Gofer's "real" vRefNum */
- long goferdirID = 0; /* Gofer's "real" dirID */
- short goferresfile = -1; /* Gofer's resource file no. */
-
- static RgnHandle cursorRgn; /* Cursor region for WaitNextEvent */
-
- Boolean quit = FALSE; /* Set when finished */
-
- extern jmp_buf catch_error; /* The error jump buffer, used by longjmp */
-
- Bool USER_ABORT = FALSE; /* Has the user Pressed CMD-. */
- extern Boolean EOFread; /* Has the user Pressed CMD-ENTER */
- extern Boolean HandlingEvents; /* Is the Programmer Handling Events in Gofer */
-
- int HeapPC = DEFAULT_HEAP_PERCENTAGE; /* % Remaining memory for Heap */
- unsigned MinMemSize = DEFAULT_MIN_MEM_SIZE; /* Minimum Memory to run in */
- #define MIN_INIT_SIZE 320000 /* Minimum Memory to start up */
-
- unsigned ExtraStack = 0; /* How much extra stack to reserve on startup */
-
-
- char *undoBuffer=NIL; /* The characters which can be "undone" */
-
-
- /* Forward declarations */
-
- Boolean cursorkey(); /* Is this key a cursor key */
- extern OSType preftype; /* The type of the Gofer Preferences file */
- extern Boolean scrapVisible; /* Is the scrap (clipboard) window visible */
- extern DescType savemethod; /* How to do global saves */
-
-
- /*****************************************************************************
-
- Interacting with our environment.
-
- ******************************************************************************/
-
-
- /*
- ObtainEnvironment determines whether WaitNextEvent etc are available.
- System 7 should use Gestalt -- KH
- */
-
- #define WNETrapNumber 0xA860 /* WaitNextEvent trap */
- #define CCTrapNumber 0xAA1B /* GetCCursor trap */
- #define CITrapNumber 0xAA1E /* GetCIcon trap */
-
- extern savedir(short vrefnum, long dirID, Boolean reset);
-
- ObtainEnvironment()
- {
- SysEnvRec environ;
- Str255 goferVolName;
-
- /* If no default volume, use Gofer's folder */
- // if(GetVol(goferVolName, &goferWDRefNum) != noErr)
- if(TRUE)
- {
- FCBPBRec fcb;
- fcb.ioNamePtr = NULL;
- fcb.ioCompletion = NULL;
- fcb.ioVRefNum = 0;
- fcb.ioRefNum = goferresfile;
- fcb.ioFCBIndx = 0;
- PBGetFCBInfo(&fcb,FALSE);
- gofervol = fcb.ioFCBVRefNum;
- goferdirID = fcb.ioFCBParID;
- }
- else
- (void) getwdinfo(goferWDRefNum, &gofervol, &goferdirID);
-
- savedir(gofervol,goferdirID,TRUE);
-
- (void) SysEnvirons(1, &environ); /* How old is this system? */
-
- if (environ.machineType < 0) /* Negative if really old */
- {
- WNEAvailable = FALSE;
- CCAvailable = FALSE;
- CIAvailable = FALSE;
- HasAppleEvents = FALSE;
- systemVersion = 0x0000;
- }
- else
- {
- WNEAvailable = TrapAvailable(WNETrapNumber, ToolTrap);
- CCAvailable = TrapAvailable(CCTrapNumber, ToolTrap);
- CIAvailable = TrapAvailable(CITrapNumber, ToolTrap);
- systemVersion = environ.systemVersion;
-
- HasAppleEvents = systemVersion >= 0x0700;
- if(HasAppleEvents)
- InstallAEHandlers();
- }
-
- if (WNEAvailable)
- cursorRgn = NewRgn();
- }
-
-
-
- /*****************************************************************************
-
- General event-handling code.
-
- ******************************************************************************/
-
-
- /*
- Disk Insertion event.
-
- Format the disk if an unformatted disk is inserted.
- */
-
-
- void DoDiskEvent()
- {
- if (HiWord(myEvent.message) != noErr)
- {
- myEvent.where.h = ((qd.screenBits.bounds.right - qd.screenBits.bounds.left) / 2) - (304 / 2);
- myEvent.where.v = ((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) / 3) - (104 / 2);
-
- InitCursor();
- (void) DIBadMount(myEvent.where, myEvent.message);
- }
- }
-
-
-
- /*
- Handle menus -- whether from mouse downs or keys.
- */
-
- void DoMenu(result,modifiers)
- long result;
- short modifiers;
- {
- short menu = HiWord(result);
- short item = LoWord(result);
-
- if (menu != 0 && item != 0)
- {
- Handle_Gofer_Menu(menu, item, modifiers);
- drawcursor(myEvent, FALSE);
- AdjustMenus(FALSE);
- }
- }
-
-
-
- /*
- Window Zooming -- Macintosh System 3.2 or Later.
- */
-
-
- void DoZoom(whichWindow, code)
- WindowPtr whichWindow;
- short code;
- {
- if (whichWindow != NIL)
- {
- if (TrackBox(whichWindow, myEvent.where, code) == TRUE)
- {
- GrafPtr saveport;
-
- GetPort(&saveport);
- SetPort(whichWindow);
- EraseRect(&whichWindow->portRect);
- ZoomWindow(whichWindow, code, TRUE);
- SetPort(saveport);
-
- ResizeTheWindow(whichWindow);
- }
- }
- }
-
-
-
- /*
- Window resizing.
- */
-
-
- void DoGrow(whichWindow)
- WindowPtr whichWindow;
- {
- Rect OldRect;
- Rect GrowRect;
-
- long growResult;
- short newWidth, newHeight;
-
- if (whichWindow != NIL)
- {
- /* Remember previous rectangle */
- OldRect = whichWindow->portRect;
-
- /* Set the grow rectangle -- minimum 100x64; "infinite" maximum */
- SetRect(&GrowRect, 100, 64, 32767, 32767);
-
- /* Get user input */
- growResult = GrowWindow(whichWindow, myEvent.where, &GrowRect);
- newWidth = LoWord(growResult);
- newHeight = HiWord(growResult);
-
- /* If the new size is different from the previous one, resize the window appropriately */
- if ( (newWidth != 0 && newHeight != 0)
- && (newWidth != (OldRect.right - OldRect.left) || newHeight != (OldRect.bottom - OldRect.top)) )
- {
- GrafPtr saveport;
-
- GetPort(&saveport);
- SetPort(whichWindow);
- EraseRect(&whichWindow->portRect);
- InvalRect(&whichWindow->portRect);
- SetPort(saveport);
-
- SizeWindow(whichWindow, newWidth, newHeight, TRUE);
- ResizeTheWindow(whichWindow);
- }
- }
- }
-
-
-
- /*
- Move a window.
- */
-
- DoDrag(whichWindow)
- WindowPtr whichWindow;
- {
- Rect screenRect = qd.screenBits.bounds;
-
- SelectWindow(whichWindow);
-
- DragWindow(whichWindow, myEvent.where, &screenRect);
-
- MoveTheWindow(whichWindow);
- }
-
-
-
- /*
- Handle a press in a goaway box.
- */
-
- DoGoAway(whichWindow)
- WindowPtr whichWindow;
- {
- int windex;
-
- /*
- NB: This will not work for user-defined windows -- something
- more sophisticated is needed.
- */
- if (TrackGoAway(whichWindow,myEvent.where))
-
- /* Normal Gofer window */
- if((windex = findMyWindow(whichWindow))!=ILLEGAL_WINDOW)
- {
- if(myEvent.modifiers&optionKey)
- IconiseWindow(windex);
-
- else if (closethewindow(windex,"closing"))
- /* SKIP */;
- }
-
- /* Desk accessory */
- else if (((WindowPeek)whichWindow)->windowKind < 0)
- {
- CloseDeskAcc(((WindowPeek)whichWindow)->windowKind);
- thefrontwindow = ILLEGAL_WINDOW;
- }
-
- /* User-defined window */
- else
- {
- HideWindow(whichWindow);
- thefrontwindow = ILLEGAL_WINDOW;
- }
- }
-
-
-
- /*
- Handle a mouse click in the body of a window.
-
- Select the window if it's not the front window.
- Handle the mouse click after selecting the window
- only if the window is iconic (so select and drag is
- one operation rather than two for iconic windows).
- */
-
- DoInContent(whichWindow)
- WindowPtr whichWindow;
- {
- int windex = findMyWindow(whichWindow);
- if(!iconic(windex) && whichWindow != FrontWindow())
- SelectWindow(whichWindow);
- else
- {
- SetPort(whichWindow);
- DoTheWindow(whichWindow,&myEvent);
- }
- }
-
-
-
- /*
- Handle window update events.
- */
-
- void DoUpdate()
- {
- WindowPtr whichWindow = (WindowPtr)myEvent.message;
-
- UpdateTheWindow(whichWindow);
- }
-
-
-
- /*
- Handle window activation/deactivation.
- */
-
-
- void DoActivate()
- {
- /* Copy scrap whenever we become active */
- if (thefrontwindow == ILLEGAL_WINDOW)
- {
- TEFromScrap();
- loadscrap();
- }
-
- ActivateTheWindow((WindowPtr)myEvent.message,
- (myEvent.modifiers & activeFlag) != 0);
- drawcursor(myEvent,TRUE);
- }
-
-
-
- /*
- Handle an OS event, such as MultiFinder suspend/resume.
- */
-
- void DoOSEvent()
- {
- if((myEvent.message & osEvtMessageMask) == SuspResEvt)
- {
- inForeground = (myEvent.message & resumeFlag) != 0;
-
- if (inForeground)
- {
- /* Resume Gofer */
- WindowPtr frontwp;
-
- /* We only copy the System scrap to the TextEdit scrap if we're requested to */
- if (myEvent.message & convertClipboardFlag)
- {
- TEFromScrap();
- loadscrap();
- }
-
- /* If the scrap has been hidden, then show it */
- if ( scrapVisible && !((WindowPeek)WINDOW(scrap))->visible )
- ShowWindow(WINDOW(scrap));
-
- /* Activate the frontmost window if there is one and it belongs to us */
- frontwp = FrontWindow();
- if (frontwp != NIL && ((WindowPeek)frontwp)->windowKind > 0)
- ActivateTheWindow(FrontWindow(),TRUE);
- }
- else
- {
- /* Suspend Gofer */
- if(thefrontwindow != ILLEGAL_WINDOW)
- ActivateTheWindow(WINDOW(thefrontwindow),FALSE);
-
- if(scrapVisible)
- HideWindow(WINDOW(scrap));
- }
- AdjustMenus(FALSE);
- }
- }
-
-
- /*
- Handle a high-level Apple Event, such as open application,
- print document etc.
-
- System-7 specific.
- */
-
- void DoHighLevelEvent()
- {
- OSErr resultCode;
-
- resultCode = AEProcessAppleEvent(&myEvent);
- if (resultCode != noErr)
- {
- char resultStr[10];
- sprintf(resultStr,"%u",resultCode);
- paramtext("",resultStr,"","");
- StopAlert(Res_AppleEvent_Failed_Alert,NIL);
- }
- else
- AdjustMenus(FALSE);
- }
-
-
-
- /* K and M define memory sizes for convenience when setting heap etc. */
-
- #define K 1024
- #define M K*K
-
- #define MASTER_BLOCKS 5 /* How many extra blocks of handles to allocate. This is a guess */
-
- InitMemory()
- {
- long maxblock; /* Largest block during startup */
- unsigned heapsize; /* Heap size as determined during initialisation */
- int i;
-
- /* Set the stack space according to the amount of heap available */
-
- heapsize = GetApplLimit() - ApplicZone();
-
- if(ExtraStack == 0)
- ExtraStack = heapsize > 2*M? heapsize/15:
- heapsize > 1*M? 32*K:
- heapsize > 800*K? 16*K:
- heapsize > 600*K? 8*K:
- heapsize > 400*K? 4*K:
- 0*K;
-
- if(ExtraStack > 0)
- SetApplLimit(GetApplLimit()-ExtraStack);
-
- for(i=0;i<MASTER_BLOCKS;++i)
- MoreMasters(); /* Allow more handles */
- MaxApplZone(); /* Extend the heap up to its limit */
-
- /* Before even trying to start up, check our memory size */
- if((maxblock=MaxBlock()) < MIN_INIT_SIZE)
- {
- SysBeep(3);
- exit(1);
- }
- }
-
-
-
- /*****************************************************************************
-
- The main Program.
-
- *************************** balTextRect;
- GrafPtr saveport;
-
- GetPort(&saveport);
- SetPort(WINDOW(thefrontwindow));
-
- globalTextRect = (*TEHANDLE(thefrontwindow))->viewRect;
- LocalToGlobalRect(&globalTextRect);
-
- if (PtInRect(event.where, &globalTextRect))
- {
- SetCursor(*ibeamcurs);
- if (adjustRegion)
- RectRgn(cursorRgn, &globalTextRect);
- }
- else
- {
- SetCursor(&(qd.arrow));
- }
-
- SetPort(saveport);
- }
- /* If we don't have an editable window, then we just need an arrow */
- else
- {
- SetCursor(&(qd.arrow));
- if (adjustRegion)
- RectRgn(cursorRgn, &worldRect);
- }
- }
-
-
-
- safeexit(n)
- {
- mprintf("\n{{Gofer interpreter exited, code %d}}\n",n);
- longjmp(catch_error,n);
- }
-